package com.cloud.zuul.config.security;

import com.google.gson.Gson;
import com.lwj.framework.degest.DigestSignature;
import com.lwj.framework.security.AuthEntity;
import com.lwj.framework.security.auth.OAuthUtils;
import com.netflix.zuul.exception.ZuulException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.SpringSecurityMessageSource;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.stereotype.Component;

import javax.naming.NoPermissionException;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
@Component
public class SecurityFilter {
	static Logger logger = LoggerFactory.getLogger(SecurityFilter.class);

	@Value("${security.ignore.zuul.uri.regex}")
	private String ingoreUriRegex;

	@Value("${security.user.signing}")
	private String userSigning;

	@Value("${security.iauthorization.signature}")
	private boolean iauthSign;

	protected Gson gson = new Gson();
	protected volatile Pattern ingorePattern = null;

	protected volatile DigestSignature digestSignature;

	public void initIngorePattern() {
		if (ingorePattern == null) {
			synchronized (this) {
				if (ingorePattern == null) {
					try {
						ingorePattern = Pattern.compile(ingoreUriRegex);
					} catch (Exception e) {
						logger.error("ingoreRegex Pattern compile error", e);
					}
				}
			}
		}
	}

	protected DigestSignature getDigestSignature() {
		if (digestSignature == null) {
			synchronized (this) {
				if (digestSignature == null) {
					digestSignature = new DigestSignature(userSigning);
				}
			}
		}
		return digestSignature;
	}

	/**
	 * 匿名访问校验
	 *
	 * @return
	 * @throws ZuulException
	 */
	public Boolean isAllowAnonymous(Map<String, String> head) {
		Boolean check=false;
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		AuthEntity authEntity = new AuthEntity();
		// 匿名访问
		 if (authentication instanceof AnonymousAuthenticationToken) {
//			 check=true;
		 }
		 //OAuth2A加密时，添加了userid，roles，校验时取出来，，加密设置服务校验token	String authinfo = encode(authEntity); head.put(OAuthUtils.Iauthorization, authinfo);
		if (authentication instanceof OAuth2Authentication) {
			OAuth2Authentication oauth2Authentication = (OAuth2Authentication) authentication;
			String userid = String.valueOf(oauth2Authentication.getPrincipal());
			List<String> roles = new ArrayList<String>();
			for (GrantedAuthority granted : oauth2Authentication.getAuthorities()) {
				roles.add(granted.getAuthority());
			}
			authEntity.setUid(userid);
			authEntity.setRls(roles);
		}
		authEntity.setIsd(OAuthUtils.False);
		String authinfo = encode(authEntity);
		head.put(OAuthUtils.Iauthorization, authinfo);
		return check;
	}

	/**
	 * 无权限访问异常
	 *
	 * @return
	 */
	protected Map<String, String> accessDeniedException() {
		String msg = SpringSecurityMessageSource.getAccessor().getMessage("AbstractAccessDecisionManager.accessDenied",
				"Access is denied");
		Map<String, String> exception = new HashMap<>();
		exception.put("sMessage", msg);
		exception.put("nStatusCode", String.valueOf(403));
		exception.put("errorCause", "Access is denied");
		return exception;
	}

	/**
	 * 用户信息编码
	 *
	 * @param authEntity
	 * @return
	 */
	protected String encode(AuthEntity authEntity) {
		String encode = null;
		if (iauthSign) {
			try {
				encode = digestSignatureEncode(authEntity);
			} catch (Exception e) {
				logger.error("digest signature encode authVo error", e);
				encode = jsonEncode(authEntity);
			}
		} else {
			encode = jsonEncode(authEntity);
		}
		return encode;
	}

	/**
	 * 用户信息编码
	 *
	 * @param authEntity
	 * @return
	 * @throws Exception
	 */
	protected String jsonEncode(AuthEntity authEntity) {
		return gson.toJson(authEntity);
	}

	/**
	 * 用户信息编码
	 *
	 * @param authEntity
	 * @return
	 * @throws Exception
	 */
	protected String digestSignatureEncode(AuthEntity authEntity) throws Exception {
		return getDigestSignature().encode(authEntity);
	}

	/**
	 * 是否是忽略校权的资源
	 *
	 * @param request
	 * @return
	 */
	protected boolean isIngoreUri(HttpServletRequest request) {
		boolean isIngore = false;
		initIngorePattern();
		if (ingorePattern != null) {
			String servletPath = request.getServletPath();
			isIngore = ingorePattern.matcher(servletPath).find();
		}
		return isIngore;
	}

}
